package edu.xidian.sei.stream

import java.text.DecimalFormat
import java.util.function.BiFunction

import edu.xidian.sei.Grid._
import edu.xidian.sei._

import scala.math._

/**
 * Created by xd_zhiwang on 2016/10/23.
 */
case class GridMapFourDimen(space: Space, reactor: ClusteringReactor, toVisit: Boolean) extends GridMap(space, reactor, toVisit) {

  override def touch(location: Location) {
    val countNow = count.incrementAndGet()
    val countTmp = tmpcount.get()
    if (countNow == tgap) {
      val writer = new java.io.PrintWriter("location_" + tgap)
      val format = new DecimalFormat("0.0000");
      location2Index.foreach { loc =>
        val formatarray = loc._1.dimensions.map { x => format.format(x) }
        writer.println(formatarray.mkString(",") + "=>" + loc._2.dimensions.mkString(","))
      }
      location2Index.clear()
      writer.close()
      val rs = snapshot(countNow, countTmp)
      learn_new_parameters(rs._1, rs._2)
      if (rs._3.size != 0) {
        reactor.clustering(countNow.toString, rs._3, Map(Grid.DensityName -> Cl, "toVisit" -> toVisit))
      } else {
        println("没有网格可以聚类")
      }

      tmpcount.addAndGet(countNow)
    }

    val index = calcIndex(location)
    location2Index += Tuple2(location, index)
    if (datas.contains(index)) {
      val grid = datas(index)
      val tc = count.get
      val pow_coeff = pow(LAMBDA, tc - grid.updatedAt)
      val tem_D = pow_coeff * grid.density + 1.0
      grid.center = relocate(grid.center, location, pow_coeff, grid.density, tem_D)
      grid.density = tem_D
      grid.updatedAt = tc
    } else {
      datas.put(index, Grid(index, location, 1, count.get))
    }

    //    datas.compute(calcIndex(location), new BiFunction[Index, Grid, Grid]() {
    //      def apply(k: Index, old: Grid): Grid = {
    //        location2Index += Tuple2(location, k)
    //        if (null == old) {
    //          Grid(k, location, 1, count.get)
    //        } else {
    //          val tc = count.get
    //          val pow_coeff = pow(LAMBDA, tc - old.updatedAt)
    //          val tem_D = pow_coeff * old.density + 1.0
    //          Grid(k, relocate(old.center, location, pow_coeff, old.density, tem_D), tem_D, tc)
    //        }
    //      }
    //    })
  }

  override def snapshot(tc: Long, tcbefore: Long): Tuple3[BigDecimal, BigDecimal, collection.Map[Index, Grid]] = {
    var ret = 0.0
    var cnt = 0
    //val at = new Array[(Int, Int)](space.dimension)
    //    for (i <- 0 until space.dimension) at(i) = (Int.MaxValue, Int.MinValue)
    val keys = datas.keys
    val map = new collection.mutable.HashMap[Index, Grid]
    //    val densityThreshold = 2.0 / 3.0 * 1.0 * (1 - pow(LAMBDA, tc - tcbefore + 1)) / (N * (1 - LAMBDA))
    //  println(densityThreshold)
    
    datas.keys.foreach { key =>
      val grid = datas(key)
      val newGrid = Grid(key, grid.center, pow(LAMBDA, tc - grid.updatedAt) * grid.density, tc)
      if (newGrid.density <= Cl * (1 - pow(LAMBDA, tc - grid.updatedAt + 1))) {
        if (readyToDelSet.contains(grid.id)) {
          //datas.remove(grid.id)
        } else {
          readyToDelSet.add(grid.id)
        } //删除零星网格
      } else if (newGrid.density > Cl && newGrid.density < Cm) {
        //cm 密集->过渡 cl 过渡->稀疏
        map.put(key, newGrid)
        ret += newGrid.density
        cnt += 1
      } else if (newGrid.density >= Cm) {
        ret += newGrid.density
        cnt += 1
        map.put(key, newGrid)
      }
      //      else {
      //        map.put(key, newGrid)
      //      }
    }
    //map.values.toList
    //println(ret + "  " + cnt)
    (ret / cnt, 0, map)
  }
}
